package com.zh.web.controller.mp;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.AopLog;
import com.zh.business.service.mp.impl.TaxiOrderInfoServiceImpl;
import com.zh.business.service.web.common.IDCommonCodeService;
import com.zh.zhbootcommon.common.CommonKey;
import com.zh.zhbootcommon.common.RedisKey;
import com.zh.zhbootcommon.common.result.impl.ResultCode;
import com.zh.zhbootcommon.config.annotation.AutoIdempotent;
import com.zh.zhbootcommon.config.annotation.DistributedLock;
import com.zh.zhbootcommon.config.annotation.VerifyToken;
import com.zh.zhbootcommon.config.exception.ZhBootException;
import com.zh.zhbootcommon.config.redis.RedisLock;
import com.zh.zhbootcommon.domain.DPage;
import com.zh.zhbootcommon.domain.DResult;
import com.zh.zhbootcommon.entity.common.CommonCode;
import com.zh.zhbootcommon.entity.taxi.DTaxiAddressInfo;
import com.zh.zhbootcommon.entity.taxi.DTaxiOrderInfo;
import com.zh.zhbootcommon.entity.taxi.DUserOrderRelation;
import com.zh.business.service.taxi.IDTaxiAddressInfoService;
import com.zh.business.service.taxi.IDUserOrderRelationService;
import com.zh.business.vo.mp.TaxiOrderReq;
import com.zh.business.vo.mp.TaxiOrderRep;
import com.zh.zhbootcommon.utils.code.CreateOrderUtil;
import com.zh.zhbootcommon.utils.common.RedisUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.Objects;

/**
 * 描述: 小程序用户订单
 *
 * @author: yanglin
 * @Date: 2021-08-19-9:48
 * @Version: 1.0
 */
@Slf4j
@AutoIdempotent
@RestController
@RequestMapping("/mp/o/v1")
@Api(value = "小程序用户订单")
@AopLog(type = "小程序用户订单", stackTraceOnErr = true)
public class OrderController {

    @Autowired
    RedisUtils redisUtils;

    @Autowired
    RedisLock redisLock;

    @Autowired
    TaxiOrderInfoServiceImpl orderInfoService;

    @Autowired
    IDTaxiAddressInfoService addressInfoService;

    @Autowired
    IDUserOrderRelationService uoRelationService;

    @Autowired
    IDCommonCodeService codeService;

    @ApiOperation(value = "用户订单列表接口")
    @PostMapping("/taxiOrderList")
    public DResult taxiOrderList(@RequestBody TaxiOrderReq orderReq, @RequestParam int page, @RequestParam int limit) {
        // 根据用户openId查询订单信息
        if (Objects.isNull(orderReq)) {
            throw new ZhBootException("订单参数不能为空!");
        }
        Page<TaxiOrderRep> orderRepPage = orderInfoService.queryTaxiOrderWechat(page, limit, orderReq);
        DPage<TaxiOrderRep> orderRepDPage = DPage.to(orderRepPage);
        return DResult.of(orderRepDPage);
    }

    @ApiOperation(value = "用户订单详情接口")
    @PostMapping("/taxiOrderDetail")
    public DResult taxiOrderDetail(@RequestBody TaxiOrderReq orderReq) {
        // 根据用户openId查询订单信息
        if (Objects.isNull(orderReq)) {
            throw new ZhBootException("订单参数不能为空!");
        }
        TaxiOrderRep orderRepPage = orderInfoService.queryTaxiOrderWechatDetail(orderReq);
        return DResult.of(orderRepPage);
    }

    @Transactional
    @DistributedLock
    @ApiOperation(value = "乘客创建订单/立即打车接口")
    @PostMapping("/createTaxiOrder")
    public DResult createTaxiOrder(@RequestBody TaxiOrderReq orderReq) {
        boolean result = false;
        TaxiOrderRep orderVo = new TaxiOrderRep();
        // 起点
        String taxiFirst = orderReq.getTaxiFirst();
        String taxiFirstDetail = orderReq.getTaxiFirstDetail();
        String taxiFirstXyz = orderReq.getTaxiFirstXyz();
        // 终点
        String taxiLast = orderReq.getTaxiLast();
        String taxiLastDetail = orderReq.getTaxiLastDetail();
        String taxiLastXyz = orderReq.getTaxiLastXyz();
        // 预估费用
        Integer taxiCosts = orderReq.getTaxiCosts();
        // 预估乘客数
        Integer taxiSeatNum = orderReq.getTaxiSeatNum();
        // 打车用户OpenId
        String mOpenId = orderReq.getMOpenId();
        // 创建打车地址
        DTaxiAddressInfo addressInfo = DTaxiAddressInfo.builder()
                .taxiFirst(taxiFirst).taxiFirstDetail(taxiFirstDetail)
                .taxiLast(taxiLast).taxiLastDetail(taxiLastDetail)
                .taxiFirstXyz(taxiFirstXyz).taxiLastXyz(taxiLastXyz)
                .taxiCosts(taxiCosts).taxiSeatNum(taxiSeatNum).build();
        result = addressInfoService.save(addressInfo);
        // 创建打车订单
        DTaxiOrderInfo orderInfo = DTaxiOrderInfo.builder()
                .orderCode(CreateOrderUtil.generateOrderNo("mp"))
                .orderPrice(taxiCosts).orderStatus(CommonKey.ORDER_STATUS_10.getValue())
                .orderTaxiNum(taxiSeatNum).taxiId(addressInfo.getTaxiId())
                .build();
        result = orderInfoService.save(orderInfo);
        // 创建打车订单用户关系
        DUserOrderRelation userOrderRelation = DUserOrderRelation.builder()
                .orderId(orderInfo.getOrderId()).mOpenId(mOpenId)
                .build();
        result = uoRelationService.save(userOrderRelation);
        if (result) {
            // 订单过期时间 默认一个小时
            CommonCode commonCode = codeService.getCommonCodeByCode(CommonKey.ORDER_CREATE_TIME.getValue());
            long expireTime = 1;
            if (Objects.nonNull(commonCode)) {
                expireTime = Long.parseLong(commonCode.getCContent());
            }
            long orderExpireTime = System.currentTimeMillis() + (expireTime * 1000);
            String orderKey = RedisKey.ORDER_INFO.getValue() + orderInfo.getOrderCode();
            // 返回值
            orderVo = TaxiOrderRep.builder().orderId(orderInfo.getOrderId())
                    .orderCode(orderInfo.getOrderCode()).orderPrice(orderInfo.getOrderPrice())
                    .orderStatus(orderInfo.getOrderStatus()).orderTaxiNum(orderInfo.getOrderTaxiNum())
                    .createTime(orderInfo.getCreateTime()).mOpenId(userOrderRelation.getMOpenId())
                    .orderEndTime(orderExpireTime).addressInfo(addressInfo).build();
            redisUtils.set(orderKey, JSONUtil.toJsonStr(orderVo), expireTime);
        }
        return DResult.of(orderVo);
    }

    @DistributedLock
    @ApiOperation(value = "司机接单/抢单接口")
    @PostMapping("/receivingTaxiOrder")
    public DResult receivingTaxiOrder(@RequestBody TaxiOrderReq orderReq) {
        this.verifyOrder(orderReq);
        // 更新订单状态;
        boolean flag = orderInfoService.updateOrderStatus(orderReq.getOrderId(), CommonKey.ORDER_STATUS_20.getValue());
        if (!flag) {
            throw new ZhBootException("订单状态变更失败!");
        }
        // 更新用户订单关系;
        flag = orderInfoService.updateUserOrderRelation(orderReq.getOrderId(), orderReq.getDOpenId());
        if (flag) {
            return DResult.of(ResultCode.ORDER_RECEIVING_SUCCESS.getCode(), ResultCode.ORDER_RECEIVING_SUCCESS.getMsg());
        } else {
            throw new ZhBootException("用户订单关系变更失败!");
        }
    }

    @DistributedLock
    @ApiOperation(value = "司机抵达出发点/乘客上车接口")
    @PostMapping("/arriveFirstTaxiOrder")
    public DResult arriveFirstTaxiOrder(@RequestBody TaxiOrderReq orderReq) {
        this.verifyOrder(orderReq);
        // 更新订单状态;
        boolean flag = orderInfoService.updateOrderStatus(orderReq.getOrderId(), CommonKey.ORDER_STATUS_30.getValue());
        if (flag) {
            return DResult.success();
        } else {
            throw new ZhBootException("订单状态变更失败!");
        }
    }

    @DistributedLock
    @ApiOperation(value = "司机已接到乘客/行驶中接口")
    @PostMapping("/arriveRunTaxiOrder")
    public DResult arriveRunTaxiOrder(@RequestBody TaxiOrderReq orderReq) {
        this.verifyOrder(orderReq);
        // 更新订单状态;
        boolean flag = orderInfoService.updateOrderStatus(orderReq.getOrderId(), CommonKey.ORDER_STATUS_40.getValue());
        if (flag) {
            return DResult.success();
        } else {
            throw new ZhBootException("订单状态变更失败!");
        }
    }

    @DistributedLock
    @ApiOperation(value = "司机抵达目的接口")
    @PostMapping("/arriveLastTaxiOrder")
    public DResult arriveLastTaxiOrder(@RequestBody TaxiOrderReq orderReq) {
        this.verifyOrder(orderReq);
        // 更新订单状态;
        boolean flag = orderInfoService.updateOrderStatus(orderReq.getOrderId(), CommonKey.ORDER_STATUS_50.getValue());
        if (flag) {
            return DResult.success();
        } else {
            throw new ZhBootException("订单状态变更失败!");
        }
    }

    @DistributedLock
    @ApiOperation(value = "司机/乘客取消订单接口")
    @PostMapping("/cancelTaxiOrder")
    public DResult cancelTaxiOrder(@RequestBody TaxiOrderReq orderReq) {
        this.verifyOrder(orderReq);
        // 更新订单状态;
        boolean flag = orderInfoService.updateOrderStatus(orderReq.getOrderId(), CommonKey.ORDER_STATUS_80.getValue());
        if (flag) {
            return DResult.success();
        } else {
            throw new ZhBootException("订单状态变更失败!");
        }
    }

    @DistributedLock
    @ApiOperation(value = "关闭订单接口")
    @PostMapping("/closeTaxiOrder")
    public DResult closeTaxiOrder(@RequestBody TaxiOrderReq orderReq) {
        this.verifyOrder(orderReq);
        // 更新订单状态;
        boolean flag = orderInfoService.updateOrderStatus(orderReq.getOrderId(), CommonKey.ORDER_STATUS_70.getValue());
        if (flag) {
            return DResult.success();
        } else {
            throw new ZhBootException("订单状态变更失败!");
        }
    }

    /**
     * 订单数据验证
     *
     * @param orderReq
     */
    public void verifyOrder(TaxiOrderReq orderReq) {
        // 获取订单信息
        if (Objects.isNull(orderReq)) {
            throw new ZhBootException("参数为空!");
        }
        DTaxiOrderInfo orderInfo = orderInfoService.getOrderInfo(orderReq.getOrderId());
        if (Objects.isNull(orderInfo)) {
            throw new ZhBootException("订单不存在!");
        }
        orderReq.setOrderCode(orderInfo.getOrderCode());
        if (!orderReq.getOrderStatus().equals(orderInfo.getOrderStatus())) {
            throw new ZhBootException("订单已被处理!");
        }
    }

}
